Skip to content

feat(html)!: address an edit by element id, not by document path - #872

Merged
andiwand merged 1 commit into
mainfrom
feat/text-edit-by-id
Sep 10, 2026
Merged

feat(html)!: address an edit by element id, not by document path#872
andiwand merged 1 commit into
mainfrom
feat/text-edit-by-id

Conversation

@andiwand

@andiwand andiwand commented Sep 10, 2026

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

First of a five-PR stack that brings text documents and presentations up to
what spreadsheets already do: editing across runs, new paragraphs, and a
delete or replace that reaches across both. docs/design/document-editing.md,
added here, records the decisions the whole stack rests on.

What this one does

An edit operation names its element by the id the render writes into the page,
data-odr-id, rather than by a DocumentPath. The envelope moves to
{"version": 2, …} and version 1 is refused rather than read.

Why: a path is positional. The moment an operation inserts a paragraph,
every path recorded after it in the same log names a different element, so a
log of more than one structural operation cannot be replayed. An id does not
move. This is decision 4 of docs/design/editing.md, now that there is
something that needs it.

An editable render addresses its paragraphs as well as its runs, because a
paragraph is what a split or an insert anchors on.

Element::identifier() and Document::element_by_id() are the two ends of the
address, in C++ and in the python, jni and apple bindings.

Breaking

Wire only, and only for our own editor's envelope. Nothing outside the tests
read data-odr-path.

Reference output

The markup change moves 275 reference files across the stack (attributes only —
the visible text of every one is byte-identical, checked). The pin advance
comes after the stack lands
, so compare-html stays red on these five PRs
until then.

An operation names its element by the id the render writes into the page,
`data-odr-id`, and the envelope moves to version 2. A path is positional,
so it names a different element the moment an operation inserts one -
which the structural edits this prepares for do. An id does not move.

An editable render addresses its paragraphs as well as its runs, because a
paragraph is what a split or an insert anchors on.

`Element::identifier()` and `Document::element_by_id()` are the two ends of
the address, in C++ and in the python, jni and apple bindings.

`docs/design/document-editing.md` records the decisions this work rests on.
It sits beside `spreadsheet-editing.md`: one document per editor, named
after the view it edits.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKFKbUVCYF2VhujdmjhhPW
@andiwand
andiwand force-pushed the feat/text-edit-by-id branch from b7195cf to 12310b4 Compare September 10, 2026 12:56
@andiwand
andiwand merged commit 4b645a3 into main Sep 10, 2026
25 checks passed
@andiwand
andiwand deleted the feat/text-edit-by-id branch September 10, 2026 12:57
andiwand added a commit that referenced this pull request Sep 10, 2026
`odr.editing.getOperations()` and `odr.generateDiff()` stated
`"version": 1` while `Document::edit` has taken 2 since #872, so every
save the browser produced was refused with "unsupported edit version".

Nothing caught it: the check pages read the operations and never the
version, and the wasm and gtest suites write their own envelope by hand.
So a check on each page that produces one now asserts it.


Claude-Session: https://claude.ai/code/session_01KKFKbUVCYF2VhujdmjhhPW

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant